<script lang="ts" setup>
import type { Component } from 'vue';
import { computed, getCurrentInstance, onMounted, useTemplateRef } from 'vue';
import {
  ElCheckbox,
  ElCheckboxGroup,
  ElDatePicker,
  ElInput,
  ElInputNumber,
  ElOption,
  ElRadio,
  ElRadioGroup,
  ElRate,
  ElSelect,
  ElSlider,
  ElSwitch,
  ElTimePicker,
  ElTimeSelect,
  ElTreeSelect
} from 'element-plus';
import type { FormInstance, FormRules } from 'element-plus';
import { omit } from 'lodash-es';
// import BaseSelect from './BaseSelect.vue';
// import BaseCheckboxGroup from './BaseCheckboxGroup.vue';
// import BaseRadioGroup from './BaseRadioGroup.vue';
import BaseUpload from './BaseUpload.vue';

// 定义单个表单项的类型
type FormItem = {
  label: string;
  key: string;
  type: string | Component;
  placeholder?: string;
  span?: number;
  style?: string;
  hidden?: boolean;
  options?: Array<{ label: string; value: string | number }>;
  brand?: string;
  props?: Record<string, any>;
  valueFormat?: string;
  controls?: boolean;
  rules?: Array<Record<string, any>>;
  onClick?: () => void;
};

interface Props {
  formItems: FormItem[];
  rules: FormRules;
}

// 定义组件的属性
const props = defineProps<Props>();

// 计算可见的表单项
const items = computed(() => props.formItems.filter(item => !item.hidden));

// 定义表单的数据模型
const modelValue: Record<string, any> = defineModel();

// 定义表单组件的映射关系
const componentMap: Record<string, Component> = {
  input: ElInput,
  number: ElInputNumber,
  select: ElSelect,
  datePicker: ElDatePicker,
  checked: ElCheckboxGroup,
  radio: ElRadioGroup,
  slider: ElSlider,
  rate: ElRate,
  switch: ElSwitch,
  textarea: ElInput,
  timePicker: ElTimePicker,
  timeSelect: ElTimeSelect,
  upload: BaseUpload,
  treeSelect: ElTreeSelect
};

// 根据表单项获取对应的组件
const getComponent = (item: { type: string | Component }) => {
  const { type } = item;
  if (type && typeof type !== 'string') return type;

  return componentMap[(item.type as keyof typeof componentMap) || 'input'];
};
// 映射子组件
const childComponetMap: Record<string, Component> = {
  select: ElOption,
  checked: ElCheckbox,
  radio: ElRadio
};
const getChildComponent = (item: { type: string | Component }) => {
  return childComponetMap[item.type as keyof typeof childComponetMap] || null;
};

// 定义根属性，这些属性不传递给组件
const rootProps = ['key', 'label', 'type', 'span', 'hidden', 'rules'];

// 获取传递给组件的属性
const getProps = (item: FormItem) => {
  if (item.props) return item.props;
  const restProps = omit(item, rootProps);

  return item.brand ? { ...restProps, type: restProps.brand } : { ...restProps };
};

// 使用模板引用获取表单实例
const formBuilsRef = useTemplateRef<FormInstance>('formBuilsRef');
const instance = getCurrentInstance();

// 组件挂载后，将表单实例的方法暴露给父组件
onMounted(() => {
  if (instance && instance.exposed && formBuilsRef.value && formBuilsRef.value.$.exposed) {
    Object.assign(instance.exposed, formBuilsRef.value.$.exposed);
  } else {
    console.error('Component instance or formBuilsRef is not properly exposed or initialized.');
  }
});

// 暴露组件实例的方法
defineExpose(instance?.exposed ?? {});
</script>

<template>
  <ElForm
    ref="formBuilsRef"
    :model="modelValue"
    :rules="rules"
    label-width="auto"
    label-suffix=" : "
    require-asterisk-position="left"
    scroll-to-error
  >
    <ElRow :gutter="24">
      <ElCol v-for="item in items" :key="item.key" :span="item.span || 24">
        <ElFormItem :label="item.label" :prop="item.key">
          <slot :name="item.key">
            <component :is="getComponent(item)" v-bind="getProps(item)" v-model="modelValue[item.key]">
              <template v-if="item.options">
                <component :is="getChildComponent(item)" v-for="option in item.options" :key="option" v-bind="option" />
              </template>
            </component>
          </slot>
        </ElFormItem>
      </ElCol>
    </ElRow>
  </ElForm>
</template>
